package com.ht.base.system.biz.manager.impl;

import com.ht.base.system.biz.convert.SysDeptBeanUtil;
import com.ht.base.system.biz.manager.SysDeptManager;
import com.ht.base.system.biz.mapper.SysDeptMapper;
import com.ht.base.system.biz.mapper.SysUserMapper;
import com.ht.base.system.common.pojo.bo.SysDeptBO;
import com.ht.base.system.common.pojo.qto.SysDeptQTO;
import com.ht.base.system.common.pojo.vo.TreeSelect;
import com.ht.base.system.dao.domain.SysDeptDO;
import com.ht.base.system.dao.domain.SysUserDO;
import org.base.common.appexception.AppErrorCodeEnum;
import org.base.common.appexception.AppException;
import org.base.common.constans.SystemConstant;
import org.base.common.page.PageBO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class SysDeptManagerImpl implements SysDeptManager {
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private SysUserMapper sysUserMapper;

    @Override
    public Boolean saveDept(SysDeptBO dept) throws AppException {
        if (dept == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (StringUtils.isBlank(dept.getDeptName())) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (dept.getParentId() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_ERROR);
        }
        SysDeptDO count = new SysDeptDO();
        count.setParentId(dept.getParentId());
        count.setDeptName(dept.getDeptName());
        if (sysDeptMapper.countByName(count) > 0) {
            throw new AppException("同一部门下不能有相同的部门名称");
        }
        setParentDept(dept);

        sysDeptMapper.insertDept(SysDeptBeanUtil.sysDeptBOToDO(dept));

        return Boolean.TRUE;
    }

    private void setParentDept(SysDeptBO dept) {
        if (dept.getParentId().longValue() == 0) {
            dept.setAncestors(dept.getParentId() + "");
        } else {
            SysDeptDO parent = sysDeptMapper.findByDeptId(dept.getParentId());
            if (parent == null) {
                throw new AppException("父级目录不存在，请刷新后重试");
            }
            dept.setAncestors(parent.getAncestors() + "," + parent.getId());
        }
    }

    @Override
    public Boolean updateDept(SysDeptBO dept) throws AppException {
        if (dept == null || dept.getSysDeptId() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        SysDeptDO old = sysDeptMapper.findByDeptId(dept.getSysDeptId());
        if (old == null) {
            throw new AppException(AppErrorCodeEnum.UPDATE_DATE_NOT_EXISTS);
        }
        Boolean flag1 = dept.getParentId() != null && dept.getParentId().longValue() != old.getParentId().longValue();
        if (flag1) {
            setParentDept(dept);
        }
        Boolean flag2 = StringUtils.isNotBlank(dept.getDeptName()) && !dept.getDeptName().equals(old.getDeptName());
        if (flag1 || flag2) {
            SysDeptDO count = new SysDeptDO();
            count.setParentId(dept.getParentId());
            count.setDeptName(dept.getDeptName());
            if (sysDeptMapper.countByName(count) > 0) {
                throw new AppException("同一部门下不能有相同的部门名称");
            }
        }
        SysDeptDO deptDO = SysDeptBeanUtil.sysDeptBOToDO(dept);
        return sysDeptMapper.updateById(deptDO);
    }

    @Override
    public Boolean delDept(Long sysDeptId) throws AppException {
        if (sysDeptId == null) {
            return false;
        }
        SysDeptDO count = new SysDeptDO();
        count.setParentId(sysDeptId);
        if (sysDeptMapper.countByName(count) > 0) {
            throw new AppException("该部门下存在下级部门，不能删除");
        }
        SysUserDO user = new SysUserDO();
        user.setSysDeptId(sysDeptId);
        if (sysUserMapper.countByCondition(user) > 0) {
            throw new AppException("该部门下存在绑定的用户，不能删除");
        }

        return sysDeptMapper.removeById(sysDeptId);
    }

    @Override
    public SysDeptBO findDeptById(Long sysDeptId) throws AppException {
        return SysDeptBeanUtil.sysDeptDOToBO(sysDeptMapper.findByDeptId(sysDeptId));
    }

    @Override
    public PageBO<SysDeptBO> findDeptForPage(SysDeptQTO qto) throws AppException {
        return null;
    }

    @Override
    public List<SysDeptBO> findSysDeptList(SysDeptQTO qto) throws AppException {
        qto.setNeedPaging(false);
        List<SysDeptDO> list = sysDeptMapper.findForPage(qto);
        //校验列表中是否有完整的数据列，如果缺少则补充缺少的数据
        getParent(list);

        return SysDeptBeanUtil.doList2BOList(list);
    }

    private void getParent(List<SysDeptDO> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            Set<Long> ids = new HashSet<>();
            List<Long> idList = new ArrayList<>(list.stream().map(SysDeptDO::getId).collect(Collectors.toSet()));
            for (SysDeptDO dept : list) {
                if (dept.getParentId().longValue() == 0L) {
                    continue;
                }
                String[] strId = dept.getAncestors().split(",");
                for (String id : strId) {
                    if (SystemConstant.STR_0.equals(id) || idList.contains(Long.parseLong(id))) {
                        continue;
                    }
                    ids.add(Long.parseLong(id));
                }
            }
            if (ids.size() > 0) {
                List<SysDeptDO> deptByIds = sysDeptMapper.findDeptByIds(ids);
                list.addAll(deptByIds);
            }
        }
    }

    @Override
    public List<SysDeptBO> buildDeptTree(List<SysDeptBO> deptList) throws AppException {
        List<SysDeptBO> returnList = new ArrayList<SysDeptBO>();
        List<Long> tempList = deptList.stream().map(SysDeptBO::getSysDeptId).collect(Collectors.toList());
        for (SysDeptBO dept : deptList) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(deptList, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = deptList;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysDeptBO> list, SysDeptBO t) {
        // 得到子节点列表
        List<SysDeptBO> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDeptBO tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDeptBO> list, SysDeptBO t) {
        return getChildList(list, t).size() > 0;
    }

    /**
     * 得到子节点列表
     */
    private List<SysDeptBO> getChildList(List<SysDeptBO> list, SysDeptBO t) {
        List<SysDeptBO> tlist = new ArrayList<SysDeptBO>();
        Iterator<SysDeptBO> it = list.iterator();
        while (it.hasNext()) {
            SysDeptBO dept = it.next();
            if (dept.getParentId() != null && dept.getParentId().longValue() == t.getSysDeptId().longValue()) {
                tlist.add(dept);
            }
        }
        return tlist;
    }

    @Override
    public List<TreeSelect> buildTreeSelect(List<SysDeptBO> deptTree) throws AppException {
        List<TreeSelect> treeSelects = deptTree.stream().map(TreeSelect::new).collect(Collectors.toList());
        return treeSelects;
    }
}
